package com.ruoyi.learn.java.design.pattern.behavior;

/**
 * 迭代器模式 (Iterator Pattern) 示例：遍历不同实现的餐厅菜单。
 */
import java.util.*;

/**
 * 迭代器模式 (Iterator Pattern) 完整示例
 * 演示如何使用自定义迭代器遍历不同底层数据结构的聚合对象。
 */
public class IteratorPatternDemo {

    // 1. 定义自定义的 Iterator 接口
    public interface Iterator<T> {
        boolean hasNext();
        T next();
    }

    // 2. 定义聚合接口 (Aggregate)
    public interface Menu {
        Iterator<MenuItem> createIterator();
    }

    // 3. 菜单项类
    public static class MenuItem {
        private String name;
        private String description;
        private boolean vegetarian;
        private double price;

        public MenuItem(String name, String description, boolean vegetarian, double price) {
            this.name = name;
            this.description = description;
            this.vegetarian = vegetarian;
            this.price = price;
        }

        // Getter 方法
        public String getName() {
            return name;
        }

        public String getDescription() {
            return description;
        }

        public boolean isVegetarian() {
            return vegetarian;
        }

        public double getPrice() {
            return price;
        }

        @Override
        public String toString() {
            return name + ", $" + price + " -- " + description;
        }
    }

    // 4. 具体聚合类 1: DinerMenu (使用 ArrayList 存储)
    public static class DinerMenu implements Menu {
        private List<MenuItem> menuItems;

        public DinerMenu() {
            menuItems = new ArrayList<>();
            addItem("Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99);
            addItem("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99);
            addItem("Soup of the day", "Soup of the day, with a side of potato salad", false, 3.29);
            addItem("Hotdog", "A hot dog, with saurkraut, relish, onions, topped with cheese", false, 3.05);
        }

        public void addItem(String name, String description, boolean vegetarian, double price) {
            MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
            menuItems.add(menuItem);
        }

        // 实现 createIterator，返回自定义的迭代器
        @Override
        public Iterator<MenuItem> createIterator() {
            return new DinerMenuIterator();
        }

        // 自定义迭代器实现类
        private class DinerMenuIterator implements Iterator<MenuItem> {
            private int position = 0; // 当前位置

            @Override
            public boolean hasNext() {
                return position < menuItems.size();
            }

            @Override
            public MenuItem next() {
                if (!hasNext()) {
                    throw new NoSuchElementException("No more elements in DinerMenu");
                }
                MenuItem menuItem = menuItems.get(position);
                position++;
                return menuItem;
            }
        }
    }

    // 5. 具体聚合类 2: PancakeHouseMenu (使用 HashMap 存储)
    public static class PancakeHouseMenu implements Menu {
        private Map<String, MenuItem> menuItems; // 使用 name 作为 key

        public PancakeHouseMenu() {
            menuItems = new HashMap<>();
            addItem("K&B's Pancake Breakfast", "Pancakes with scrambled eggs, and toast", true, 2.99);
            addItem("Regular Pancake Breakfast", "Pancakes with fried eggs, sausage", false, 2.99);
            addItem("Blueberry Pancakes", "Pancakes made with fresh blueberries", true, 3.49);
            addItem("Waffles", "Waffles, with your choice of blueberries or strawberries", true, 3.59);
        }

        public void addItem(String name, String description, boolean vegetarian, double price) {
            MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
            menuItems.put(name, menuItem);
        }

        // 实现 createIterator，返回自定义的迭代器
        @Override
        public Iterator<MenuItem> createIterator() {
            return new PancakeHouseMenuIterator();
        }

        // 自定义迭代器实现类
        // 关键：我们不直接暴露 java.util.Iterator，而是封装它。
        private class PancakeHouseMenuIterator implements Iterator<MenuItem> {
            private java.util.Iterator<Map.Entry<String, MenuItem>> standardIterator; // 底层使用标准库的 Iterator

            public PancakeHouseMenuIterator() {
                // 获取 HashMap entrySet 的标准库 Iterator
                this.standardIterator = menuItems.entrySet().iterator();
            }

            @Override
            public boolean hasNext() {
                return standardIterator.hasNext();
            }

            @Override
            public MenuItem next() {
                if (!hasNext()) {
                    throw new NoSuchElementException("No more elements in PancakeHouseMenu");
                }
                // 从 Map.Entry 中提取 MenuItem
                Map.Entry<String, MenuItem> entry = standardIterator.next();
                return entry.getValue(); // 返回 MenuItem 对象
            }
        }
    }

    // 6. 客户端类: Waitress
    public static class Waitress {
        private Menu pancakeHouseMenu;
        private Menu dinerMenu;

        public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
            this.pancakeHouseMenu = pancakeHouseMenu;
            this.dinerMenu = dinerMenu;
        }

        public void printMenu() {
            System.out.println("=== MENU ===");
            printMenu(pancakeHouseMenu);
            System.out.println("---");
            printMenu(dinerMenu);
        }

        private void printMenu(Menu menu) {
            Iterator<MenuItem> iterator = menu.createIterator();
            while (iterator.hasNext()) {
                MenuItem menuItem = iterator.next();
                System.out.println(menuItem);
            }
        }

        // 只打印素食菜单项
        public void printVegetarianMenu() {
            System.out.println("=== VEGETARIAN MENU ===");
            printVegetarianMenu(pancakeHouseMenu);
            printVegetarianMenu(dinerMenu);
        }

        private void printVegetarianMenu(Menu menu) {
            Iterator<MenuItem> iterator = menu.createIterator();
            while (iterator.hasNext()) {
                MenuItem menuItem = iterator.next();
                if (menuItem.isVegetarian()) {
                    System.out.println(menuItem);
                }
            }
        }
    }

    // 7. 主方法 (程序入口)
    public static void main(String[] args) {
        // 创建具体的菜单
        PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
        DinerMenu dinerMenu = new DinerMenu();

        // 创建服务员
        Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);

        // 打印完整菜单
        waitress.printMenu();

        System.out.println("\n"); // 分隔线

        // 打印素食菜单
        waitress.printVegetarianMenu();
    }
}